package com.lwl.concurrency.collection;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * <pre>
 * 带有延迟元素的线程安全列表
 * 存放到DelayQueue类中的元素必须继承Delay接口
 * </pre>
 * 
 * @author lwl 2018年1月16日 下午9:52:33
 */
public class DelayQueueTest {

	public static class Event implements Delayed {

		private Date startDate;

		public Event(Date startDate) {
			this.startDate = startDate;
		}

		/**
		 * 如果执行这个方法的对象的延期小于作为参数传入的对象的延期，该方法返回小于0的值。
		 * 如果执行这个方法的对象的延期大于作为参数传入的对象的延期，该方法返回大于0的值。
		 * 如果这两个对象的延期相等，则返回0
		 */
		@Override
		public int compareTo(Delayed o) {
			long timeStamp = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
			if (timeStamp < 0) {
				return -1;
			} else if (timeStamp > 0) {
				return 1;
			}
			return 0;
		}

		@Override
		public long getDelay(TimeUnit unit) {
			Date now = new Date();
			//毫秒
			long duration = startDate.getTime() - now.getTime();
			//将毫秒转为指定的时间计量单位对应的时间
			return unit.convert(duration, TimeUnit.MILLISECONDS);
		}
	}

	public static class Task implements Runnable {

		private int id;
		private DelayQueue<Event> queue;

		public Task(int id, DelayQueue<Event> queue) {
			this.id = id;
			this.queue = queue;
		}

		@Override
		public void run() {
			Date now = new Date();
			Date delay = new Date();
			delay.setTime(now.getTime() + (id * 1000));
			System.out.printf("Thread %s: %s\n", id, delay);
			for (int i = 0; i < 100; i++) {
				Event event = new Event(delay);
				queue.add(event);
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		DelayQueue<Event> queue = new DelayQueue<>();
		Thread threads[] = new Thread[5];
		for (int i = 0; i < threads.length; i++) {
			Task task = new Task(i + 1, queue);
			threads[i] = new Thread(task);
		}
		for (int i = 0; i < threads.length; i++) {
			threads[i].start();
		}
		for (int i = 0; i < threads.length; i++) {
			threads[i].join();
		}
		do {
			int counter = 0;
			Event event;
			do {
				event = queue.poll();
				if (event != null)
					counter++;
			} while (event != null);
			System.out.printf("At %s you have read %d events\n", LocalDateTime.now(), counter);
			TimeUnit.MILLISECONDS.sleep(500);
		} while (queue.size() > 0);
	}

}
